package com.zhangh.summer.admin.biz.login.impl;

import com.zhangh.summer.admin.biz.app.AppBiz;
import com.zhangh.summer.admin.biz.menu.MenuBiz;
import com.zhangh.summer.admin.biz.org.OrgBiz;
import com.zhangh.summer.admin.model.bo.MenuBO;
import com.zhangh.summer.admin.model.bo.OrgBO;
import com.zhangh.summer.admin.model.bo.SessionUserBO;
import com.zhangh.summer.admin.model.enums.AppFrameEnum;
import com.zhangh.summer.admin.model.po.AdAppPO;
import com.zhangh.summer.admin.support.utils.BeanGenerator;
import com.zhangh.summer.admin.support.utils.MD5Util;
import com.zhangh.summer.admin.support.utils.UUIDGenerator;
import com.zhangh.summer.admin.support.utils.json.JsonEncoder;
import com.zhangh.summer.admin.biz.log.LoginLogBiz;
import com.zhangh.summer.admin.biz.login.LoginBiz;
import com.zhangh.summer.admin.biz.user.UserBiz;
import com.zhangh.summer.admin.model.bo.LoginBO;
import com.zhangh.summer.admin.model.po.AdLoginLogPO;
import com.zhangh.summer.admin.model.po.AdUserPO;
import com.zhangh.summer.admin.support.ds.common.MixedDS;
import com.zhangh.summer.admin.support.exception.BizException;
import com.zhangh.summer.admin.support.session.SessionUser;
import com.zhangh.summer.admin.support.util.RSAUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.security.GeneralSecurityException;
import java.util.Date;
import java.util.List;

/**
 * @description: TODO
 * @author: zhanghui  zhanghlucky@163.com
 * @create: 2021-09-28 23:33
 **/
@Service
@Slf4j
public class LoginBizImpl implements LoginBiz {
    @Resource
    private MixedDS mixedDS;
    @Autowired
    private UserBiz userBiz;
    @Autowired
    private OrgBiz orgBiz;
    @Autowired
    private LoginLogBiz loginLogBiz;
    @Autowired
    private MenuBiz menuBiz;
    @Autowired
    private AppBiz appBiz;


    @Override
    @Transactional
    public SessionUser login(LoginBO loginBO) {
        String loginData=loginBO.getLoginData();
        String ip=loginBO.getIp();
        try {
            loginData= RSAUtil.decrypt(loginData);
            loginBO= JsonEncoder.DEFAULT.decode(loginData,LoginBO.class);
            AdUserPO adUserPO=this.userBiz.getUserByLoginName(loginBO.getLoginName());
            if (null==adUserPO){
                log.info("登录失败，用户名不存在 loginName {}",loginBO.getLoginName());
                throw BizException.exception("登录失败，用户名/密码错误！");
            }

            if (!adUserPO.getIsEnable()){
                log.info("登录失败，用户被禁用 loginName {}",loginBO.getLoginName());
                throw BizException.exception("登录失败，用户被禁用！");
            }
            //判断签名时间
            String sign=loginBO.getSign();
            if (Long.valueOf(sign)+5*60*10000<System.currentTimeMillis()){//签名5分钟有效
                log.error("签名失效 sign {}",sign);
                throw BizException.exception("登录失败，签名失效！");
            }

            String salt=adUserPO.getSalt();
            String password= MD5Util.MD5(loginBO.getLoginPwd()+salt);
            if (password.equals(adUserPO.getLoginPwd())){
                log.info("用户 {} 登录成功",loginBO.getLoginName());
                //生成token
                String token= UUIDGenerator.random32UUID()+"_"+System.currentTimeMillis();
                OrgBO orgBO=this.orgBiz.getOrgBO(adUserPO.getOrgID());
                SessionUser sessionUser=new SessionUser();
                sessionUser.setLoginName(adUserPO.getLoginName());
                sessionUser.setUserID(adUserPO.getId());
                sessionUser.setUserName(adUserPO.getUserName());
                sessionUser.setLoginTime(new Date());
                sessionUser.setOrgID(orgBO.getId());
                sessionUser.setOrgName(orgBO.getOrgName());
                sessionUser.setToken(token);
                sessionUser.setIp(ip);
                this.mixedDS.redis().set(token,JsonEncoder.DEFAULT.encode(sessionUser),60*60*24*7);//7天有效
                //写登录日志
                AdLoginLogPO adLoginLogPO= BeanGenerator.copy(sessionUser,AdLoginLogPO.class);
                this.loginLogBiz.saveLog(adLoginLogPO);
                return sessionUser;
            }else{
                log.info("登录失败，密码错误 loginName {}",loginBO.getLoginName());
                throw BizException.exception("登录失败，用户名/密码错误！");
            }
        } catch (GeneralSecurityException e) {
            log.error("解密失败",e);
            e.printStackTrace();
            throw BizException.exception("验证失败！{0}",e.getMessage());
        }
    }

    @Override
    public SessionUserBO loginWithMenu(LoginBO loginBO) {
        SessionUser sessionUser=this.login(loginBO);
        List<MenuBO> menuBOList=this.menuBiz.getUserAuthMenuList(sessionUser.getUserID());
        List<AdAppPO> appList=this.appBiz.getAdAppPOList(AppFrameEnum.MICRO.getValue());
        MenuBO homeMenu=this.menuBiz.getHomeMenu();
        SessionUserBO sessionUserBO=new SessionUserBO();
        sessionUserBO.setMenuList(menuBOList);
        sessionUserBO.setAppList(appList);
        sessionUserBO.setHomeMenu(homeMenu);
        sessionUserBO.setSessionUser(sessionUser);
        return sessionUserBO;
    }

    @Override
    @Transactional
    public void loginOut(String token) {
        this.mixedDS.redis().del(token);
        this.loginLogBiz.loginOut(token);
        log.info("用户退出 token {}" ,token);
    }

    @Override
    public boolean loginCheck(String token) {
        String user=this.mixedDS.redis().get(token);
        if (StringUtils.isNotBlank(user)){
            return true;
        }
        return false;
    }

    @Override
    public String getSessionUserFromRedis(String token) {
        String user=this.mixedDS.redis().get(token);
        if (StringUtils.isNotBlank(user)){
            return user;
        }
        return null;
    }
}
